﻿namespace BM.Tools.WebControls.MForm.Design
{
    using System;
    using System.IO;
    using System.Reflection;
    using System.Xml.Schema;
    using System.Xml.Serialization;

    /// <summary>
    /// A static class that converts assembly to Xml Schema definition
    /// </summary>
    public static class TypeToSchemaConverter
    {
        /// <summary>
        /// Creates Xml Schema set definition from an assembly file name
        /// </summary>
        /// <param name="fileName">
        /// The file name.
        /// </param>
        /// <returns>
        /// Xml Schema Set object
        /// </returns>
        public static XmlSchemaSet ExportAssembly(string fileName)
        {
            return ExportAssembly(fileName, NoValidationCallback);
        }

        /// <summary>
        /// Creates Xml Schema set definition from an assembly file name, providing a way to attach validation event handler
        /// </summary>
        /// <param name="fileName">
        /// The file name.
        /// </param>
        /// <param name="validationHandler">
        /// The validation handler.
        /// </param>
        /// <returns>
        /// Xml Schema Set object
        /// </returns>
        public static XmlSchemaSet ExportAssembly(string fileName, ValidationEventHandler validationHandler)
        {
            var assembly = Assembly.Load(File.ReadAllBytes(fileName));
            return ExportTypes(assembly.GetTypes(), validationHandler);
        }

        /// <summary>
        /// Creates Xml Schema set definition for an array of types, providing a way to attach validation event handler
        /// </summary>
        /// <param name="types">
        /// The types.
        /// </param>
        /// <param name="validationHandler">
        /// The validation handler.
        /// </param>
        /// <returns>
        /// Xml Schema Set object
        /// </returns>
        public static XmlSchemaSet ExportTypes(Type[] types, ValidationEventHandler validationHandler)
        {
            var reflectionImporter = new XmlReflectionImporter();
            var schemas = new XmlSchemas();
            var schemaExporter = new XmlSchemaExporter(schemas);

            foreach (var type in types)
            {
                ExportType(reflectionImporter, type, schemaExporter);
            }

            schemas.Compile(validationHandler, false);
                    
            var schemaSet = new XmlSchemaSet();
            foreach (XmlSchema schema in schemas)
            {
                schemaSet.Add(schema);                
            }            
            
            return schemaSet;
        }

        private static void ExportType(XmlReflectionImporter importer, Type type, XmlSchemaExporter exporter)
        {
            try
            {
                XmlTypeMapping xmlTypeMapping = importer.ImportTypeMapping(type);
                exporter.ExportTypeMapping(xmlTypeMapping);
            }
            catch (Exception)
            {
            }
        }

        private static void NoValidationCallback(object sender, ValidationEventArgs e)
        {            
        }        
    }
}
